<?php
/**
 * builder.php
 * Created by PhpStorm.
 * User: 江小波
 * Date: 2018/09/08
 * Time: 22:01
 */
/**
 * 需求：
 * 我们假设一个快餐店的商业案例，其中，一个典型的套餐可以是一个汉堡（Burger）和一杯冷饮（Cold drink）。
 * 汉堡（Burger）可以是素食汉堡（Veg Burger）或鸡肉汉堡（Chicken Burger），它们是包在纸盒中。
 * 冷饮（Cold drink）可以是可口可乐（coke）或百事可乐（pepsi），它们是装在瓶子中。
 * 1. 创建一个表示食物条目和食物包装的接口 Item 。
 * 2. 创建一个接口 Packing 包装来区别是纸盒还是瓶子
 */
interface Item {
    // 食物条目的名称
    public function name();
    // 食物包装
    public function packing();
    // 食物价格
    public function price();
}
interface Packing {
    public function pack();
}
// 纸盒包装
class Wrapper implements Packing {
    # Override
    public function pack(){
        return 'Wrapper';
    }
}
// 瓶子包装
class Bottle implements Packing {
    # Override
    public function pack(){
        return 'Bottle';
    }
}

// 汉堡的抽象类
abstract class Burger implements Item {
    # Override
    // 汉堡食物都是用纸盒包装
    public function packing(){
        return new Wrapper();
    }
    // 食物价格
    abstract public function price();
}
// 饮料的抽象类
abstract class ColdDrink implements Item {
    # Override
    // 饮料食物都是用瓶子包装
    public function packing(){
        return new Bottle();
    }
    // 食物价格
    abstract public function price();
}

// 素食汉堡实现具体类
class VegBurger extends Burger {
    # Override
    public function price(){
        return 25.0;
    }
    # Override
    public function name(){
        return 'Veg Burger';
    }
}
// 鸡肉汉堡实现具体类
class ChickenBurger extends Burger {
    # Override
    public function price(){
        return 50.5;
    }
    # Override
    public function name(){
        return 'Chicken Burger';
    }
}
// 可口可乐实现具体类
class Coke extends ColdDrink {
    # Override
    public function price(){
        return 30.0;
    }
    # Override
    public function name(){
        return 'Coke';
    }
}
// 百事可乐实现具体类
class Pepsi extends ColdDrink {
    # Override
    public function price(){
        return 35.0;
    }
    # Override
    public function name(){
        return 'Pepsi';
    }
}

// 创建一个 Meal 类，带有上面定义的 Item 对象
class Meal {
    private $items = [];

    public function addItem(Item $item){
        $this->items[] = $item;
    }
    public function getCost(){
        $cost = 0;
        foreach($this->items as $item){
            $cost += $item->price();
        }
        return $cost;
    }
    public function showItems(){
        foreach($this->items as $item){
            echo("Item : ".$item->name());
            echo(", Packing : ".$item->packing()->pack());
            echo(", Price : ".$item->price()."\n");
        }
    }
}

// 定义套餐，或者单买
class MealBuilder {
    /**
     * 套餐1：素食汉堡+可口可乐
     * @return Meal
     */
    public function package1(){
        $meal = new Meal();
        $meal->addItem(new VegBurger());
        $meal->addItem(new Coke());
        return $meal;
    }
    /**
     * 套餐2：鸡肉汉堡+百事可乐
     * @return Meal
     */
    public function package2(){
        $meal = new Meal();
        $meal->addItem(new ChickenBurger());
        $meal->addItem(new Pepsi());
        return $meal;
    }
}

// A顾客:套餐1
echo "A顾客-套餐1\n";
$a = new MealBuilder();
$t = $a->package1();
echo "总计".$t->getCost()."\n";
$t->showItems();

// B顾客:套餐2
echo "B顾客-套餐2\n";
$b = new MealBuilder();
$t = $b->package2();
echo "总计".$t->getCost()."\n";
$t->showItems();

// C顾客:只想要一个素食汉堡
echo "B顾客-素食汉堡\n";
$c = new VegBurger();
echo "总计".$c->price()."\n";
echo("Item : ".$c->name());
echo(", Packing : ".$c->packing()->pack());
echo(", Price : ".$c->price()."\n");

echo "\n\nend";